package paa.simulator.data;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import paa.crawlers.delicious.Crawler;
import paa.simulator.grafo.VideoPool;
import paa.simulator.grafo.VideoPool.Video;

public class DataExtract {

	private static final String EMPTY_NAME = "";
	private static final String LIST_DELIMITERS = "\\[|\\]";
	private static final String LIST_SPLITER = ",\\s";
	private static final String VID_TAG_SPLITER = "\\s:\\s";
	private static final String HTTP_GDATA_YOUTUBE_COM_FEEDS_API_VIDEOS = "http://gdata.youtube.com/feeds/api/videos/";
	
	public static void main(String[] args) throws Exception {
		if (args == null || args.length < 3) {
			System.err.println("usage: java " + Crawler.class + " <in dir> <people data> <video data> <tag data>");
			System.exit(1);
		}
		
		File dir = new File(args[0]);
		if (!dir.exists()) {
			System.err.println("Directory does exists, exiting.");
			System.exit(1);
		}
		
		//Lendo arquivos
		File[] subdirs = dir.listFiles();
		if (subdirs == null || subdirs.length == 0) {
			System.err.println("Directory is empty, exiting.");
			System.exit(1);
		}
		
		BufferedWriter pessoaWriter = new BufferedWriter(new FileWriter(args[1]));
		pessoaWriter.write("#Pessoa \t QTDVideos \t QTDTags \t QTDSubs \t QTDUpload");
		pessoaWriter.newLine();
		BufferedWriter videoWriter = new BufferedWriter(new FileWriter(args[2]));
		videoWriter.write("#Video \t QTDTags \t Popularidade");
		videoWriter.newLine();
		BufferedWriter tagWriter = new BufferedWriter(new FileWriter(args[3]));
		tagWriter.write("#Tag \t Popularidade");
		tagWriter.newLine();
		
		extractData(subdirs, pessoaWriter, videoWriter, tagWriter);
		
		pessoaWriter.close();
		videoWriter.close();
		tagWriter.close();
	}
	
	public static void extractData(File[] subdirs, BufferedWriter pessoaWriter, BufferedWriter videoWriter, BufferedWriter tagWriter) throws Exception {
		Pattern userNamePattern = Pattern.compile("#user:\\s(.*)");
		Pattern uploadsPattern = Pattern.compile("#uploads:\\s\\[(.*),\\s\\]");
		Pattern favoritesPattern = Pattern.compile("#favorites:\\s\\[(.*),\\s\\]");
		Pattern subscriptionsPattern = Pattern.compile("#subscriptions:\\s\\[(.*),\\s\\]");
		
		HashMap<Video, Integer> video2popularity = new HashMap<Video, Integer>();
		
		for (File subdir : subdirs) {
	
			String id = null;
			int qtdFav = 0;
			int qtdTagsFav = 0;
			int qtdSubs = 0;
			int qtdUps = 0;
			int qtdTagsUps = 0;
			
			for (File file : subdir.listFiles()) {
				BufferedReader reader = null;
				try {
					reader = new BufferedReader(new FileReader(file));
					String line;
					while((line = reader.readLine()) != null) {
						
						Matcher userNameMatcher = userNamePattern.matcher(line);
						Matcher uploadsMatcher = uploadsPattern.matcher(line);
						Matcher favoritesMatcher = favoritesPattern.matcher(line);
						Matcher subscriptionsMatcher = subscriptionsPattern.matcher(line);
						
						if (userNameMatcher.matches()) {
							id = userNameMatcher.group(1);
						} else if (favoritesMatcher.matches()) {
							String group = favoritesMatcher.group(1);
							String[] strings = group.split(HTTP_GDATA_YOUTUBE_COM_FEEDS_API_VIDEOS);
							
							HashSet<Video> favorites = extractVideos(strings, video2popularity);
							HashSet<Integer> tags = new HashSet<Integer>();
							for (Video v : favorites) {

								Integer integer = video2popularity.get(v);
								if (integer == null) {
									integer = 0;
								}
								video2popularity.put(v, integer.intValue() + 1);
								
								tags.addAll(v.getTags());
							}
							
							qtdTagsFav = tags.size();
							qtdFav = favorites.size();
						} else if (subscriptionsMatcher.matches()) {
							String group = subscriptionsMatcher.group(1);
							String[] strings = group.split(LIST_SPLITER);
							qtdSubs = strings.length;
						} else if (uploadsMatcher.matches()) {
							String group = uploadsMatcher.group(1);
							String[] strings = group.split(HTTP_GDATA_YOUTUBE_COM_FEEDS_API_VIDEOS);
						
							HashSet<Video> uploads = extractVideos(strings, video2popularity);
							HashSet<Integer> tags = new HashSet<Integer>();
							for (Video v : uploads) {
								tags.addAll(v.getTags());
							}
							
							qtdTagsUps = tags.size();
							qtdUps = uploads.size();
						}
					}
					
					reader.close();
					pessoaWriter.write(id + " \t " + qtdFav + " \t " + qtdTagsFav  + " \t " + qtdSubs + " \t " + qtdUps + " \t " + qtdTagsUps);
					pessoaWriter.newLine();
				} finally {						
					if (reader != null) {
						reader.close();
					}
				}
			}
		}
		
		VideoPool.getInstance().clear();
		
		Map<Integer, Integer> tag2popularity = new HashMap<Integer, Integer>();
		for (Video v : video2popularity.keySet()) {
			Set<Integer> vidTags = v.getTags();
			for (Integer t : vidTags) {
				Integer integer = tag2popularity.get(t);
				if (integer == null) {
					integer = 0;
				}
				tag2popularity.put(t, integer.intValue() + 1);
			}
			
			int quantidadeTags = vidTags.size();
			videoWriter.write(v.getID() + " \t " + quantidadeTags + " \t " + video2popularity.get(v));
			videoWriter.newLine();
		}
		video2popularity.clear();
		videoWriter.flush();
		
		for (Integer t : tag2popularity.keySet()) {
			tagWriter.write(t + " \t " + tag2popularity.get(t));
			tagWriter.newLine();
		}
		tagWriter.flush();
		tag2popularity.clear();
	}
	
	private static HashSet<Video> extractVideos(String[] strings, HashMap<Video, Integer> video2popularity) {
		HashSet<Video> vs = new HashSet<Video>();
		for (String video : strings) {
			if (video.length() != 0) {
				String[] videoTags = video.split(VID_TAG_SPLITER);
				String videoName = videoTags[0];
				int videoID = videoName.hashCode();
				
				Video instance = VideoPool.getInstance().getVideo(videoID);
				if (instance == null) {
					String tagsLine = videoTags[1];
					String[] tagTokens = tagsLine.split(LIST_SPLITER);
					
					HashSet<Integer> list = new HashSet<Integer>();
					for (String tag : tagTokens) {
						tag = tag.replaceAll(LIST_DELIMITERS, EMPTY_NAME).toLowerCase();
						list.add(tag.hashCode());
					}
					
					instance = VideoPool.getInstance().putVideo(videoID, list);
				}
				vs.add(instance);
			}
		}
		return vs;
	}
}
